namespace OneWorks.Utils.FluentData
{
    using System;
    using System.Data;

    internal class DataReader : IDataReader
    {
        public System.Data.IDataReader InnerReader { get; private set; }

        public DataReader(System.Data.IDataReader reader)
        {
            this.InnerReader = reader;
        }

        public void Close()
        {
            this.InnerReader.Close();
        }

        private T GetValue<T>(int i)
        {
            var value = this.InnerReader.GetValue(i);
            if(value == DBNull.Value)
                return default(T);
            return (T)value;
        }

        public int Depth
        {
            get { return this.InnerReader.Depth; }
        }

        public DataTable GetSchemaTable()
        {
            return this.InnerReader.GetSchemaTable();
        }

        public bool IsClosed
        {
            get { return this.InnerReader.IsClosed; }
        }

        public bool NextResult()
        {
            return this.InnerReader.NextResult();
        }

        public bool Read()
        {
            return this.InnerReader.Read();
        }

        public int RecordsAffected
        {
            get { return this.InnerReader.RecordsAffected; }
        }

        public void Dispose()
        {
            this.InnerReader.Dispose();
        }

        public int FieldCount
        {
            get { return this.InnerReader.FieldCount; }
        }

        public bool GetBoolean(int i)
        {
            return this.GetValue<bool>(i);
        }

        public bool GetBoolean(string name)
        {
            return this.GetBoolean(this.GetOrdinal(name));
        }

        public byte GetByte(int i)
        {
            return this.GetValue<byte>(i);
        }

        public byte GetByte(string name)
        {
            return this.GetByte(this.GetOrdinal(name));
        }

        public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
        {
            return this.IsDBNull(i) ? 0 : this.InnerReader.GetBytes(i, fieldOffset, buffer, bufferoffset, length);
        }

        public long GetBytes(string name, long fieldOffset, byte[] buffer, int bufferoffset, int length)
        {
            return this.GetBytes(this.GetOrdinal(name), fieldOffset, buffer, bufferoffset, length);
        }

        public char GetChar(int i)
        {
            return this.GetValue<char>(i);
        }

        public char GetChar(string name)
        {
            return this.GetChar(this.GetOrdinal(name));
        }

        public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
        {
            return this.IsDBNull(i) ? 0 : this.InnerReader.GetChars(i, fieldoffset, buffer, bufferoffset, length);
        }

        public long GetChars(string name, long fieldoffset, char[] buffer, int bufferoffset, int length)
        {
            return this.GetChars(this.GetOrdinal(name), fieldoffset, buffer, bufferoffset, length);
        }

        public System.Data.IDataReader GetData(int i)
        {
            return this.InnerReader.GetData(i);
        }

        public System.Data.IDataReader GetData(string name)
        {
            return this.GetData(this.GetOrdinal(name));
        }

        public string GetDataTypeName(int i)
        {
            return this.InnerReader.GetDataTypeName(i);
        }

        public string GetDataTypeName(string name)
        {
            return this.GetDataTypeName(this.GetOrdinal(name));
        }

        public DateTime GetDateTime(int i)
        {
            return this.GetValue<DateTime>(i);
        }

        public DateTime GetDateTime(string name)
        {
            return this.GetDateTime(this.GetOrdinal(name));
        }

        public decimal GetDecimal(int i)
        {
            return this.GetValue<decimal>(i);
        }

        public decimal GetDecimal(string name)
        {
            return this.GetDecimal(this.GetOrdinal(name));
        }

        public double GetDouble(int i)
        {
            return this.GetValue<double>(i);
        }

        public double GetDouble(string name)
        {
            return this.GetDouble(this.GetOrdinal(name));
        }

        public Type GetFieldType(int i)
        {
            return this.InnerReader.GetFieldType(i);
        }

        public Type GetFieldType(string name)
        {
            return this.GetFieldType(this.GetOrdinal(name));
        }

        public float GetFloat(int i)
        {
            return this.GetValue<float>(i);
        }

        public float GetFloat(string name)
        {
            return this.GetFloat(this.GetOrdinal(name));
        }

        public Guid GetGuid(int i)
        {
            return this.GetValue<Guid>(i);
        }

        public Guid GetGuid(string name)
        {
            return this.GetGuid(this.GetOrdinal(name));
        }

        public short GetInt16(int i)
        {
            return this.GetValue<Int16>(i);
        }

        public short GetInt16(string name)
        {
            return this.GetInt16(this.GetOrdinal(name));
        }

        public int GetInt32(int i)
        {
            return this.GetValue<int>(i);
        }

        public int GetInt32(string name)
        {
            return this.GetInt32(this.GetOrdinal(name));
        }

        public long GetInt64(int i)
        {
            return this.GetValue<long>(i);
        }

        public long GetInt64(string name)
        {
            return this.GetInt64(this.GetOrdinal(name));
        }

        public string GetName(int i)
        {
            return this.InnerReader.GetName(i);
        }

        public string GetName(string name)
        {
            return this.InnerReader.GetName(this.GetOrdinal(name));
        }

        public int GetOrdinal(string name)
        {
            return this.InnerReader.GetOrdinal(name);
        }

        public string GetString(int i)
        {
            return this.GetValue<string>(i);
        }

        public string GetString(string name)
        {
            return this.GetString(this.GetOrdinal(name));
        }

        public object GetValue(int i)
        {
            return this.GetValue<object>(i);
        }

        public object GetValue(string name)
        {
            return this.GetValue(this.GetOrdinal(name));
        }

        public int GetValues(object[] values)
        {
            return this.InnerReader.GetValues(values);
        }

        public bool IsDBNull(int i)
        {
            return this.InnerReader.IsDBNull(i);
        }

        public bool IsDBNull(string name)
        {
            return this.IsDBNull(this.GetOrdinal(name));
        }

        public object this[string name]
        {
            get { return this[this.GetOrdinal(name)]; }
        }

        public object this[int i]
        {
            get
            {
                return this.IsDBNull(i) ? null : this.InnerReader[i];
            }
        }
    }
}